Um guia detalhado sobre a API Temporal do JavaScript, uma solução moderna para lidar com datas e horas de forma eficaz em diversos contextos internacionais.
API Temporal do JavaScript: Manipulação Moderna de Data e Hora para um Público Global
O objeto `Date` do JavaScript tem sido, há muito tempo, uma fonte de frustração para desenvolvedores. Sua mutabilidade, API inconsistente e suporte fraco a fusos horários levaram à criação de inúmeras bibliotecas, como Moment.js e date-fns, para preencher as lacunas. Agora, com a API Temporal, o JavaScript oferece uma solução moderna e integrada para lidar com datas e horas com maior clareza e precisão. Este artigo fornece uma visão abrangente da API Temporal, focando em suas funcionalidades, benefícios e uso em diversos contextos internacionais.
O que é a API Temporal?
A API Temporal é um novo objeto global no JavaScript, projetado para resolver as deficiências do objeto `Date`. Ela fornece uma API limpa e imutável para trabalhar com datas, horas, fusos horários e sistemas de calendário. Crucialmente, ela visa representar conceitos de data e hora de uma forma que se alinha mais de perto com o uso e as expectativas do mundo real, tornando a internacionalização muito mais simples.
Principais Características:
- Imutabilidade: Os objetos Temporal são imutáveis, o que significa que operações como adicionar dias ou meses retornam novos objetos em vez de modificar o original. Isso elimina uma fonte comum de bugs e torna o código mais fácil de raciocinar.
- API Clara: A Temporal fornece uma API consistente e intuitiva para operações comuns de data e hora.
- Suporte a Fusos Horários: A Temporal inclui um suporte robusto para fusos horários, permitindo que você trabalhe com datas e horas em diferentes locais sem as complexidades do antigo objeto `Date`. Ela usa o banco de dados de fusos horários da IANA, garantindo informações precisas e atualizadas.
- Sistemas de Calendário: Além do calendário gregoriano, a Temporal suporta sistemas de calendário alternativos, atendendo às necessidades de diversas culturas e regiões.
- Precisão Aprimorada: A Temporal oferece precisão de nanossegundos, abordando as limitações do objeto `Date`, que é baseado em milissegundos.
Objetos Temporais Básicos
A API Temporal introduz vários novos tipos de objetos. Aqui estão alguns dos principais:
- `Temporal.PlainDate`: Representa uma data (ano, mês, dia) sem fuso horário.
- `Temporal.PlainTime`: Representa uma hora (hora, minuto, segundo, milissegundo, microssegundo, nanossegundo) sem data ou fuso horário.
- `Temporal.PlainDateTime`: Representa uma data e hora sem fuso horário.
- `Temporal.ZonedDateTime`: Representa uma data e hora com um fuso horário específico.
- `Temporal.Instant`: Representa um momento específico no tempo, medido em nanossegundos desde a época Unix (1º de janeiro de 1970 UTC).
- `Temporal.TimeZone`: Representa um fuso horário.
- `Temporal.Duration`: Representa um período de tempo (ex: 2 horas, 30 minutos).
- `Temporal.YearMonth`: Representa um ano e um mês.
- `Temporal.MonthDay`: Representa um mês e um dia.
Trabalhando com Datas
Criando um `Temporal.PlainDate`
Para criar um `Temporal.PlainDate`, você pode usar o construtor:
const plainDate = new Temporal.PlainDate(2024, 10, 27); // Ano, Mês (1-12), Dia
console.log(plainDate.toString()); // Saída: 2024-10-27
Você também pode usar o método `from`, que aceita uma string no formato ISO 8601:
const plainDateFromString = Temporal.PlainDate.from('2024-10-27');
console.log(plainDateFromString.toString()); // Saída: 2024-10-27
Obtendo Componentes da Data
Você pode acessar componentes individuais da data usando propriedades como `year`, `month` e `day`:
console.log(plainDate.year); // Saída: 2024
console.log(plainDate.month); // Saída: 10
console.log(plainDate.day); // Saída: 27
Aritmética de Datas
Para adicionar ou subtrair dias, semanas, meses ou anos, use os métodos `plus` e `minus`. Esses métodos retornam um novo objeto `Temporal.PlainDate`:
const nextWeek = plainDate.plus({ days: 7 });
console.log(nextWeek.toString()); // Saída: 2024-11-03
const lastMonth = plainDate.minus({ months: 1 });
console.log(lastMonth.toString()); // Saída: 2024-09-27
Comparando Datas
Você pode comparar datas usando o método `compare`:
const date1 = new Temporal.PlainDate(2024, 10, 27);
const date2 = new Temporal.PlainDate(2024, 11, 15);
console.log(Temporal.PlainDate.compare(date1, date2)); // Saída: -1 (date1 é anterior a date2)
Trabalhando com Horas
Criando um `Temporal.PlainTime`
Para criar um `Temporal.PlainTime`, use o construtor:
const plainTime = new Temporal.PlainTime(10, 30, 0); // Hora, Minuto, Segundo
console.log(plainTime.toString()); // Saída: 10:30:00
Ou use o método `from` com uma string de hora ISO 8601:
const plainTimeFromString = Temporal.PlainTime.from('10:30:00');
console.log(plainTimeFromString.toString()); // Saída: 10:30:00
Obtendo Componentes da Hora
console.log(plainTime.hour); // Saída: 10
console.log(plainTime.minute); // Saída: 30
console.log(plainTime.second); // Saída: 0
Aritmética de Horas
const later = plainTime.plus({ minutes: 15 });
console.log(later.toString()); // Saída: 10:45:00
Trabalhando com Data e Hora Juntos
Criando um `Temporal.PlainDateTime`
Você pode criar um `Temporal.PlainDateTime` diretamente ou combinando um `Temporal.PlainDate` e um `Temporal.PlainTime`:
const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
console.log(plainDateTime.toString()); // Saída: 2024-10-27T10:30:00
const date = new Temporal.PlainDate(2024, 10, 27);
const time = new Temporal.PlainTime(10, 30, 0);
const combinedDateTime = date.toPlainDateTime(time);
console.log(combinedDateTime.toString()); // Saída: 2024-10-27T10:30:00
Fusos Horários
Lidar com fusos horários corretamente é crucial para aplicações que lidam com usuários em diferentes locais. A API Temporal fornece um suporte robusto a fusos horários através dos objetos `Temporal.ZonedDateTime` e `Temporal.TimeZone`.
Criando um `Temporal.ZonedDateTime`
Para criar um `Temporal.ZonedDateTime`, você precisa de um `Temporal.PlainDateTime` e um identificador de fuso horário. Os identificadores de fuso horário são baseados no banco de dados de fusos horários da IANA (ex: `America/Los_Angeles`, `Europe/London`, `Asia/Tokyo`).
const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
const timeZone = 'America/Los_Angeles';
const zonedDateTime = plainDateTime.toZonedDateTime(timeZone);
console.log(zonedDateTime.toString()); // Saída: 2024-10-27T10:30:00-07:00[America/Los_Angeles] (O deslocamento dependerá das regras do horário de verão)
Alternativamente, crie um `Temporal.ZonedDateTime` a partir de um `Instant`.
const instant = Temporal.Instant.fromEpochSeconds(1666866600); // Exemplo de timestamp
const zonedDateTimeFromInstant = instant.toZonedDateTimeISO(timeZone); // Fuso horário como 'America/Los_Angeles'
console.log(zonedDateTimeFromInstant.toString());
Convertendo Entre Fusos Horários
Você pode converter um `Temporal.ZonedDateTime` para um fuso horário diferente usando o método `withTimeZone`:
const newTimeZone = 'Europe/London';
const zonedDateTimeInLondon = zonedDateTime.withTimeZone(newTimeZone);
console.log(zonedDateTimeInLondon.toString()); // Saída: 2024-10-27T18:30:00+01:00[Europe/London]
Trabalhando com Deslocamentos de Fuso Horário
O método `getOffsetStringFor` do objeto `Temporal.TimeZone` fornece a string de deslocamento para um determinado `Temporal.Instant`:
const timeZoneObject = new Temporal.TimeZone(timeZone);
const offsetString = timeZoneObject.getOffsetStringFor(zonedDateTime.toInstant());
console.log(offsetString); // Saída: -07:00 (Dependendo das regras do horário de verão)
É essencial usar os identificadores de fuso horário da IANA corretos para cálculos precisos. Esses identificadores são mantidos e atualizados regularmente para refletir mudanças no horário de verão e nas fronteiras dos fusos horários.
Durações
O objeto `Temporal.Duration` representa um período de tempo. Ele pode ser usado para adicionar ou subtrair de datas e horas.
Criando uma `Temporal.Duration`
Você pode criar uma `Temporal.Duration` usando o construtor, especificando os anos, meses, dias, horas, minutos, segundos, milissegundos, microssegundos e nanossegundos:
const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9); // Anos, Meses, Dias, Horas, Minutos, Segundos, Milissegundos, Microssegundos, Nanossegundos
console.log(duration.toString()); // Saída: P1Y2M3DT4H5M6.007008009S
Ou usando uma string de duração ISO 8601:
const durationFromString = Temporal.Duration.from('P1Y2M3DT4H5M6S');
console.log(durationFromString.toString()); // Saída: P1Y2M3DT4H5M6S
Adicionando Durações a Datas e Horas
const plainDate = new Temporal.PlainDate(2024, 10, 27);
const duration = new Temporal.Duration(0, 0, 7); // 7 dias
const newDate = plainDate.plus(duration);
console.log(newDate.toString()); // Saída: 2024-11-03
Note que adicionar durações que envolvem meses ou anos a datas requer consideração cuidadosa, pois o número de dias em um mês ou ano pode variar.
Sistemas de Calendário
A API Temporal suporta diferentes sistemas de calendário além do calendário gregoriano. Isso é crucial para aplicações que precisam lidar com datas em vários contextos culturais. Embora o suporte ainda esteja evoluindo, ele fornece uma base para expansão futura.
Usando Calendários Alternativos
Para usar um calendário específico, você pode especificá-lo ao criar objetos Temporal:
const hebrewDate = new Temporal.PlainDate(5785, 1, 1, { calendar: 'hebrew' });
console.log(hebrewDate.toString()); // A saída específica pode variar dependendo da implementação e formatação. Requer polyfill em muitos ambientes no momento da escrita.
Importante: O suporte para calendários não gregorianos pode exigir polyfills ou suporte específico do navegador/ambiente. Verifique a documentação da API Temporal e as tabelas de compatibilidade de navegadores para obter as informações mais recentes.
Formatando Datas e Horas
Embora a API Temporal se concentre na manipulação de data e hora, a formatação é normalmente tratada pelo objeto `Intl.DateTimeFormat`, que faz parte da API de Internacionalização. Os objetos Temporal funcionam perfeitamente com `Intl.DateTimeFormat`.
Usando `Intl.DateTimeFormat`
Veja como formatar um `Temporal.PlainDate` usando `Intl.DateTimeFormat`:
const plainDate = new Temporal.PlainDate(2024, 10, 27);
const formatter = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric' });
console.log(formatter.format(plainDate)); // Saída: October 27, 2024
const formatterGerman = new Intl.DateTimeFormat('de-DE', { year: 'numeric', month: 'long', day: 'numeric' });
console.log(formatterGerman.format(plainDate)); // Saída: 27. Oktober 2024
Você pode personalizar as opções de formato para atender às suas necessidades. O primeiro argumento para `Intl.DateTimeFormat` é a localidade, que determina o idioma e as convenções regionais usadas para a formatação. Usar diferentes localidades (ex: 'en-US', 'de-DE', 'fr-FR', 'ja-JP') produz diferentes formatos de saída.
Formatando `Temporal.ZonedDateTime`
A formatação de `Temporal.ZonedDateTime` é semelhante, mas você também pode incluir informações de fuso horário na saída:
const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
const timeZone = 'America/Los_Angeles';
const zonedDateTime = plainDateTime.toZonedDateTime(timeZone);
const formatter = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', timeZoneName: 'short' });
console.log(formatter.format(zonedDateTime)); // Saída: October 27, 2024, 10:30 AM PDT (A abreviação do fuso horário depende das regras do horário de verão)
Melhores Práticas de Internacionalização
Ao trabalhar com datas e horas em um contexto global, tenha em mente as seguintes melhores práticas:
- Use Identificadores de Fuso Horário da IANA: Sempre use identificadores de fuso horário da IANA (ex: `America/Los_Angeles`, `Europe/London`) para um tratamento preciso de fusos horários.
- Esteja Ciente do Horário de Verão: O horário de verão (DST) pode afetar os deslocamentos de fuso horário. A API Temporal lida automaticamente com as transições de DST.
- Use `Intl.DateTimeFormat` para Formatação: Use o objeto `Intl.DateTimeFormat` para formatar datas e horas de acordo com a localidade do usuário.
- Considere Sistemas de Calendário: Se sua aplicação precisa dar suporte a usuários em diferentes contextos culturais, considere usar sistemas de calendário alternativos.
- Armazene Datas e Horas em UTC: Ao armazenar datas e horas em um banco de dados, a melhor prática é armazená-las em UTC (Tempo Universal Coordenado) para evitar problemas com fusos horários. Em seguida, converta para a hora local para fins de exibição. A Temporal fornece métodos para converter de e para UTC.
- Teste exaustivamente: Teste sua aplicação com diferentes fusos horários, localidades e sistemas de calendário para garantir que funcione corretamente para todos os usuários.
Comparando a API Temporal com o Objeto Date Legado
Aqui está uma tabela destacando as principais diferenças e vantagens da API Temporal em comparação com o objeto `Date` legado:
Característica | Objeto `Date` Legado | API Temporal |
---|---|---|
Mutabilidade | Mutável (modifica o objeto original) | Imutável (retorna novos objetos) |
Suporte a Fuso Horário | Limitado e frequentemente problemático | Robusto e preciso, baseado no banco de dados de fusos horários da IANA |
API | Inconsistente e difícil de usar | Clara, consistente e intuitiva |
Precisão | Milissegundo | Nanossegundo |
Sistemas de Calendário | Limitado ao Gregoriano | Suporta sistemas de calendário alternativos (com suporte em evolução) |
Internacionalização | Requer bibliotecas externas para internacionalização robusta | Suporte integrado e integração perfeita com `Intl.DateTimeFormat` |
Suporte de Navegadores e Polyfills
Como uma API relativamente nova, o suporte dos navegadores para a API Temporal ainda está evoluindo. Verifique as tabelas de compatibilidade de navegadores mais recentes (por exemplo, na MDN Web Docs) para ver quais navegadores e ambientes a suportam nativamente. Para navegadores mais antigos ou ambientes sem suporte nativo, você pode usar polyfills para fornecer a funcionalidade da API Temporal. Pesquise por "Temporal API polyfill" na web para encontrar opções adequadas.
Conclusão
A API Temporal do JavaScript representa um avanço significativo no tratamento de datas e horas em JavaScript. Sua imutabilidade, API clara, suporte robusto a fusos horários e capacidades de sistemas de calendário a tornam uma ferramenta poderosa para desenvolvedores que constroem aplicações que precisam trabalhar com datas e horas de forma precisa e confiável em diversos contextos internacionais. Embora o suporte dos navegadores ainda esteja evoluindo, os benefícios da API Temporal fazem com que valha a pena aprender e adotá-la para novos projetos. Ao abraçar a API Temporal e seguir as melhores práticas de internacionalização, você pode criar aplicações que fornecem uma experiência de data e hora perfeita e precisa para usuários em todo o mundo.